package cn.dj.org.service.impl;

import cn.dj.basic.service.impl.BaseServiceImpl;
import cn.dj.basic.util.Md5Utils;
import cn.dj.basic.util.PageList;
import cn.dj.basic.util.StrUtils;
import cn.dj.org.domain.Department;
import cn.dj.org.domain.Employee;
import cn.dj.org.mapper.DepartmentMapper;
import cn.dj.org.mapper.EmployeeMapper;
import cn.dj.org.query.EmployeeQuery;
import cn.dj.org.service.EmployeeService;
import cn.dj.user.domain.Logininfo;
import cn.dj.user.mapper.LogininfoMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 业务实现类：部门
 */
//前提：扫描包路径
@Service //1.将当前类交给Spring管理 = 2.实例化对象注解 = 3.创建对象的注解[这样Spring容器中有该类的对象，才能在其他地方注入该对象]
public class EmployeeServiceImpl extends BaseServiceImpl<Employee> implements EmployeeService {
    //注入
    @Autowired
    private DepartmentMapper departmentMapper;
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private EmployeeMapper employeeMapper;
   /* @Autowired
    private EmployeeMapper employeeMapper;

    //增删改用 @Transactional 默认的readOnly = false,propagation = Propagation.REQUIRED
    @Transactional
    @Override
    public void save(Employee employee) {
        employeeMapper.save(employee);
    }
    @Transactional
    @Override
    public void update(Employee employee) {
        employeeMapper.update(employee);
    }
    @Transactional
    @Override
    public void del(Long id) {
        employeeMapper.del(id);
    }

    @Override
    public List<Employee> loadAll() {
        return employeeMapper.loadAll();
    }

    @Override
    public Employee loadById(Long id) {
        return employeeMapper.loadById(id);
    }

    @Override
    public PageList<Employee> queryPage(EmployeeQuery employeeQuery) {
       //1.查询总数量
        Integer totals = employeeMapper.queryCount(employeeQuery);
        if(totals < 1){//没有查询到数据的情况
            return new PageList<>();
        }
        //2.查询当前页的分页数据
        List<Employee> employees = employeeMapper.queryData(employeeQuery);
        return new PageList<>(totals,employees);
    }

    @Override
    public void patchDelete(List<Long> ids) {
        employeeMapper.patchDelete(ids);
    }*/

   @Override
   public List<Department> deptTree() {
       List<Department> departments = departmentMapper.loadAll();
       //1.将所有部门信息保存在map中，方便根据id去获取部门信息，就不用查数据库了
       Map<Long,Department> map = new HashMap<>();
       for (Department department : departments) {
           map.put(department.getId(),department);
       }
       List<Department> deptTree = new ArrayList<>();
       for (Department department : departments) {
           if(department.getParent_id()==null){//顶级部门
               //2.遍历所有的部门，如果是顶级部门[parent_id==null]，加到部门树
               deptTree.add(department);
           }else{
               //3.如果不是顶级部门【parent_id!=null]】，找到自己的父部门，将自己加到父部门的children集合
               //获取父部门的id - 是为了获取父部门对象 - 获取父部门的children集合
               Long parentId = department.getParent_id();
               //根据id获取父部门对象
               Department parentDepartment = map.get(parentId);
               //防止父部门数据的删除引起的空指针异常
               if(parentDepartment!=null){//为null不能调用方法，会报错
                   parentDepartment.getChildren().add(department);
               }
           }

       }
       return deptTree;
   }

    @Override
    public List<Employee> queryByShopId(Long shopId) {
        return employeeMapper.queryByShopId(shopId);
    }

    /**
     * 重写添加方法
     * 添加员工信息表的同时也有添加登录信息表
     * @param employee
     */
    @Transactional//事务管理
    @Override
    public void save(Employee employee) {//添加要加密加盐
        //处理盐值和密码
        String salt = StrUtils.getComplexRandomString(32);
        String md5Pwd = Md5Utils.encrypByMd5(employee.getPassword() + salt);
        employee.setSalt(salt);
        employee.setPassword(md5Pwd);
        //创建Logininfo对象
        Logininfo logininfo = employee2Logininfo(employee);
        //先保存Logininfo对象 - 生成自增id
        logininfoMapper.save(logininfo);//获取到自增ID
        //将id设置到employee对象中
        employee.setLogininfo_id(logininfo.getId());
        //添加管理员信息
        super.save(employee);

        //添加当前员工的角色信息
        if(employee.getRole_id()!=null) {
            employeeMapper.addRole(employee);//中间表的数据维护，在主表进行
        }
    }

    private Logininfo employee2Logininfo(Employee employee) {
        //先添加logininfo
        Logininfo logininfo = new Logininfo();
        //通过属性同名原则进行拷贝：
        BeanUtils.copyProperties(employee,logininfo);
        logininfo.setType(0);//管理员【t_user是用户表，t_employee是员工表】
        logininfo.setDisable(true);//默认启用
        return logininfo;
    }

    /**
     * 重写删除方法
     * 删除员工信息表的同时也有删除登录信息表
     * @param id
     */
    @Transactional//事务管理
    @Override
    public void del(Long id) {
        //先查询登陆信息id
        Employee employee = employeeMapper.loadById(id);
        //删除登录信息logininfo表中的信息【删除t_logininfo信息】
        logininfoMapper.del(employee.getLogininfo_id());

        //删除当前员工的角色信息：t_employee_role - 先删除中间表【断开连接即可】，再删除主表的
        employeeMapper.delRoleByEmployeeId(id);

        //调用父类方法删除employee【再删除t_employee信息】
        super.del(id);
    }

    /**
     * 重写修改方法
     * 修改员工信息表的同时也有修改登录信息表
     * @param employee
     */
    @Transactional//事务管理
    @Override
    public void update(Employee employee) {
        //处理盐值和密码
        String salt = StrUtils.getComplexRandomString(32);//随机生成32位盐值
        String md5Pwd = Md5Utils.encrypByMd5(employee.getPassword() + salt);//加密加盐
        employee.setSalt(salt);
        employee.setPassword(md5Pwd);

        //注意：修改的时候不应该修改密码 - 强制修改密码-为1

        //创建Logininfo对象：拷贝了6个数据包括id[employee的id]
        Logininfo logininfo = employee2Logininfo(employee);
        //查以前的老数据【oldEmployee是数据库里的，还没修改的】：employee里面大的数据来自于前端  -就不会有logininfo_id,shop_id
        Employee oldEmployee = employeeMapper.loadById(employee.getId());//loginfo_id
       //重新设置logininfo_id
        logininfo.setId(oldEmployee.getLogininfo_id());//然后把登录信息的唯一标识id赋值给该登录信息的id - id不变，一个人对应一条登录信息，要修改就一起修改就行了
        Logininfo dblogininfo= logininfoMapper.loadById(oldEmployee.getLogininfo_id());
        logininfo.setDisable(dblogininfo.getDisable());//保持原先的启用/禁用状态 - 因为调用employee2Logininfo方法后，状态会被值为true
        //操作数据库
        logininfoMapper.update(logininfo);//更新
        //employee - 前端传递的
        employee.setShop_id(oldEmployee.getShop_id());
        employee.setLogininfo_id(oldEmployee.getLogininfo_id());
        super.update(employee);

        //修改 = 先删除再添加
        employeeMapper.delRoleByEmployeeId(employee.getId());
        if(employee.getRole_id()!=null){
            employeeMapper.addRole(employee);
        }

      /*  //查以前的老数据：employee里面大的数据来自于前端  -就不会有logininfo_id,shop_id
        Employee oldEmployee = employeeMapper.loadById(employee.getId());//loginfo_id

        //修改user信息
        employee.setLogininfo_id(oldEmployee.getLogininfo_id());//同一条登录信息，所以从原先数据拿来设置
        employee.setShop_id(oldEmployee.getShop_id());//同一条店铺信息，所以从原先数据拿来设置进去
        super.update(employee);//更新

        //修改登陆信息
        Logininfo oldLogininfo = logininfoMapper.loadById(oldEmployee.getLogininfo_id());
        //属性同名原则：
        BeanUtils.copyProperties(employee,oldLogininfo);//把修改后的新的员工【管理员】的登录信息copy给自己先前的登录信息 - 更新登录信息
        oldLogininfo.setId(oldEmployee.getLogininfo_id());//然后把登录信息的唯一标识id赋值给该登录信息的id - id不变，一个人对应一条登录信息，要修改就一起修改就行了
        logininfoMapper.update(oldLogininfo);//更新*/

    }

    /**
     * 重写批量删除
     * @param ids
     */
    @Override
    public void patchDelete(List<Long> ids) {
        for (Long id : ids) {
            del(id);
        }
    }
}
